using System.Collections;
using System.IO;
using System.Text;

namespace Rhino.net {
    public class Tokenizer {
        private TextReader _reader;
        private string[] KEYWORDS = {"var", "new"};
        private Hashtable keywords = new Hashtable();

        public Tokenizer(TextReader reader) {
            _reader = reader;
            populateKeywords();
        }

        private void populateKeywords() {
            for (int i = 0; i < KEYWORDS.Length; i++) {
                keywords.Add(KEYWORDS[i], KEYWORDS[i]);
            }
        }

        public Token MakeToken(int c) {
            if (isSpace(c))
                return Token.SPACE;
            else if (isEOF(c))
                return Token.EOF;
            else if (isNewLine(c) || IsNewLineCarriageReturn(c))
                return Token.NEWLINE;
            else if (isAlpha(c)) {
                return matchString(c);
            }
            return Token.ERROR;
        }

        private bool IsNewLineCarriageReturn(int c) {
            bool isCarriageReturn = c == '\r';
            if(isCarriageReturn) {
                if(!isEOF(_reader.Peek()) && isNewLine(_reader.Peek())) {
                    c = _reader.Read();
                    return true;
                }
            }
          return false;     
        }

        private Token matchString(int c) {
            StringBuilder value = new StringBuilder();
            value.Append((char) c);
            while (!isEOF(_reader.Peek()) && isAlnum(_reader.Peek())) {
                c = _reader.Read();
                value.Append((char) c);
            }
            return resolveStringAsKeywordOrIdentifier(value);
        }

        private Token resolveStringAsKeywordOrIdentifier(StringBuilder value) {
            Token result;
            if (isKeyWord(value.ToString()))
                result = new Token(Token.KEYWORD, value.ToString());
            else
                result = new Token(Token.IDENTIFIER, value.ToString());
            return result;
        }

        private bool isKeyWord(string value) {
            return keywords.ContainsKey(value);
        }


        private bool isEOF(int c) {
            return c == -1;
        }

        private bool isNewLine(int i) {
            bool newLine = (i == '\n');
            return newLine;
        }

        private bool isAlpha(int c) {
            return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
        }

        private bool isNum(int c) {
            return c >= '0' && c <= '9';
        }

        private bool isAlnum(int c) {
            return isAlpha(c) || isNum(c);
        }

        private bool isSpace(int i) {
            bool result = i == ' ';
            return result;
        }
    }
}